﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * ZIP Digital Signature Class
 * 		Represents a digital signature that may be present in a PKZIP file. 
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.IO;

namespace Adaptive.Foundation.IO.Zip
{
    /// <summary>
    /// Represents a digital signature that may be present in a PKZIP file. 
    /// </summary>
    public sealed class ZipDigitalSignature : AiObjectBase, IStorable
    {
        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Data content signature.
        /// </summary>
        private byte[] _signature;
        /// <summary>
        /// Size of the digital signature.
        /// </summary>
        private int _sizeOfData;
        /// <summary>
        /// Digital signature byte array.
        /// </summary>
        private byte[] _signatureData;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the <see cref="ZipDigitalSignature" /> class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public ZipDigitalSignature()
            : base()
        {
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ZipDigitalSignature" /> class.
        /// </summary>
        /// <param name="signatureData">
        /// A byte array containing the data signature content.
        /// </param>
        public ZipDigitalSignature(byte[] signatureData)
            : base()
        {
            _sizeOfData = signatureData.Length;
            _signatureData = new byte[_sizeOfData];
            Array.Copy(signatureData, _signatureData, _sizeOfData);
        }
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><b>true</b> to release both managed and unmanaged resources;
        /// <b>false</b> to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if ((!Disposed) && (disposing))
            {
                if (_signatureData != null)
                {
                    Array.Clear(_signatureData, 0, _signatureData.Length);
                    _signatureData = null;
                }
            }

            _signatureData = null;
            _signature = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets the size of the data.
        /// </summary>
        /// <value>
        /// The size of the data signature content, in bytes.
        /// </value>
        public int DataSignatureLength
        {
            get
            {
                return _sizeOfData;
            }
        }
        /// <summary>
        /// Gets or sets the digital signature content.
        /// </summary>
        /// <value>
        /// A byte array containing the digital signature content.
        /// </value>
        public byte[] DigitalSignature
        {
            get
            {
                return _signatureData;
            }
            set
            {
                if (value != null)
                {
                    _sizeOfData = value.Length;
                    _signatureData = new byte[_sizeOfData];
                    Array.Copy(value, _signatureData, _sizeOfData);
                }
                else
                {
                    _sizeOfData = 0;
                    _signatureData = null;
                }
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Loads the content for the instance from the specified stream.
        /// </summary>
        /// <param name="reader">An open <see cref="BinaryReader" /> used to read data from the
        /// underlying stream.</param>
        /// <returns>
        /// <b>true</b> if the load operation is successful; otherwise, <b>false</b>.
        /// </returns>
        public bool Load(BinaryReader reader)
        {
            bool returnValue = false;

            try
            {
                _signature = reader.ReadBytes(4);
                _sizeOfData = reader.ReadInt32();
                _signatureData = reader.ReadBytes(_sizeOfData);
                returnValue = true;
            }
            catch (IOException)
            {
            }

            return returnValue;
        }
        /// <summary>
        /// Saves the content for the instance to the specified stream.
        /// </summary>
        /// <param name="writer">An open <see cref="BinaryWriter" /> used to write data to the
        /// underlying stream.</param>
        /// <returns>
        /// <b>true</b> if the save operation is successful; otherwise, <b>false</b>.
        /// </returns>
        public bool Save(BinaryWriter writer)
        {
            bool returnValue = false;

            try
            {
                writer.Write(_signature);

                if (_sizeOfData > 0)
                {
                    writer.Write(_sizeOfData);
                    writer.Write(_signatureData);
                }
                else
                    writer.Write(0);

                writer.Flush();
                returnValue = true;
            }
            catch (IOException)
            {
            }

            return returnValue;
        }
        #endregion

    }
}
